/*
 * Electron 预加载脚本（ESM）
 *
 * 职责
 * - 在 contextIsolation 开启的情况下，向渲染进程安全暴露有限能力
 * - 使用 IPC 白名单，避免任意通道访问带来的安全隐患
 * - 提供协作友好的注释与扩展点
 *
 * 使用示例（渲染进程）
 *   // 读取版本与平台信息
 *   console.log(window.electronAPI.env);
 *
 *   // 打开系统文件对话框（需要主进程实现对应 handler）
 *   const paths = await window.electronAPI.openFile();
 *
 *   // 订阅主进程事件（添加到 ON_CHANNELS 后方可使用）
 *   const off = window.electronAPI.on('app:notify', (payload) => {
 *     console.log('notify', payload);
 *   });
 *   // 取消订阅：off();
 */

import { contextBridge, ipcRenderer } from 'electron';

// IPC 白名单：仅允许列出的通道被调用或订阅
const INVOKE_CHANNELS = new Set([
  // 与主进程的 ipcMain.handle 对应
  'dialog:openFile',
]);
const ON_CHANNELS = new Set([
  // 订阅主进程通过 webContents.send/broadcast 的通道，如：'app:notify'
  // 默认留空，按需添加
]);

function isAllowed(channel, set) {
  return set.has(channel);
}

// 暴露到渲染进程的安全 API
const api = {
  // 环境/平台信息（只读，便于前端做差异化处理）
  env: {
    platform: process.platform,
    isDev: process.env.NODE_ENV === 'development',
    versions: {
      node: process.versions.node,
      chrome: process.versions.chrome,
      electron: process.versions.electron,
      v8: process.versions.v8,
    },
  },

  // 典型示例：打开系统文件选择对话框
  // 需要主进程实现：
  //   import { ipcMain, dialog } from 'electron';
  //   ipcMain.handle('dialog:openFile', async () => {
  //     const { canceled, filePaths } = await dialog.showOpenDialog({ properties: ['openFile'] });
  //     return canceled ? null : filePaths;
  //   });
  openFile: () => ipcRenderer.invoke('dialog:openFile'),

  // 泛型 invoke，受白名单保护，方便扩展更多请求-响应接口
  invoke: (channel, ...args) => {
    if (!isAllowed(channel, INVOKE_CHANNELS)) {
      throw new Error(`Blocked invoke channel: ${channel}`);
    }
    return ipcRenderer.invoke(channel, ...args);
  },

  // 订阅主进程事件（如状态变更、通知等），返回取消订阅函数
  on: (channel, listener) => {
    if (!isAllowed(channel, ON_CHANNELS)) {
      throw new Error(`Blocked on channel: ${channel}`);
    }
    const wrapped = (_event, ...args) => listener(...args);
    ipcRenderer.on(channel, wrapped);
    return () => ipcRenderer.removeListener(channel, wrapped);
  },

  // 订阅一次性事件
  once: (channel, listener) => {
    if (!isAllowed(channel, ON_CHANNELS)) {
      throw new Error(`Blocked once channel: ${channel}`);
    }
    const wrapped = (_event, ...args) => listener(...args);
    ipcRenderer.once(channel, wrapped);
  },

  // 移除某通道的所有监听（谨慎使用）
  removeAllListeners: (channel) => {
    ipcRenderer.removeAllListeners(channel);
  },
};

// 向渲染进程（Vue 组件）暴露安全 API
contextBridge.exposeInMainWorld('electronAPI', api);